// src/store/index.js
import { createStore } from 'vuex';
import router from '@/router';
import userApi from '@/api/user';

export default createStore({
  state: {
    // 用户信息
    userInfo: null,
    // 访问令牌
    accessToken: null,
    // 刷新令牌
    refreshToken: null,
    // 是否已登录
    isLogin: false,
    // Token刷新定时器
    refreshTimer: null
  },
  
  mutations: {
    // 设置用户信息
    SET_USER_INFO(state, userInfo) {
      state.userInfo = userInfo;
    },
    
    // 设置访问令牌
    SET_ACCESS_TOKEN(state, token) {
      state.accessToken = token;
    },
    
    // 设置刷新令牌
    SET_REFRESH_TOKEN(state, token) {
      state.refreshToken = token;
    },
    
    // 设置登录状态
    SET_LOGIN_STATUS(state, status) {
      state.isLogin = status;
    },
    
    // 清除用户信息
    CLEAR_USER_INFO(state) {
      state.userInfo = null;
      state.accessToken = null;
      state.refreshToken = null;
      state.isLogin = false;
    },
    
    // 设置刷新定时器
    SET_REFRESH_TIMER(state, timer) {
      state.refreshTimer = timer;
    }
  },
  
  actions: {
    // 用户登录
    async login({ commit, dispatch }, loginData) {
      // 移除不必要的 try/catch，让错误向上抛出
      const response = await userApi.login(loginData);
      
      // 保存用户信息和令牌
      commit('SET_USER_INFO', response.user);
      commit('SET_ACCESS_TOKEN', response.access_token);
      commit('SET_REFRESH_TOKEN', response.refresh_token);
      commit('SET_LOGIN_STATUS', true);
      
      // 计算过期时间戳（当前时间+有效期）
      const expiresAt = Date.now() + response.expires_in * 1000;
      // 保存到localStorage
      localStorage.setItem('user_info', JSON.stringify(response.user));
      localStorage.setItem('access_token', response.access_token);
      localStorage.setItem('refresh_token', response.refresh_token);
      localStorage.setItem('isLogin', 'true');
      localStorage.setItem('access_token_expires_at', expiresAt.toString());
      
      // 设置定时刷新Token（在过期前5分钟刷新）
      dispatch('scheduleTokenRefresh', response.expires_in);
      
      return response;
    },
    
    // 用户注册
    async register(registerData) {
      // 移除不必要的 try/catch，让错误向上抛出
      const response = await userApi.register(registerData);
      return response;
    },
    
    // 刷新Token
    async refreshToken({ commit, state, dispatch }) {
      if (!state.refreshToken) {
        throw new Error('没有刷新令牌');
      }
      
      try {
        const response = await userApi.refreshToken({
          refresh_token: state.refreshToken
        });
        
        // 更新访问令牌
        commit('SET_ACCESS_TOKEN', response.access_token);
        
        // 计算新的过期时间戳
        const expiresAt = Date.now() + response.expires_in * 1000;
        
        // 更新localStorage
        localStorage.setItem('access_token', response.access_token);
        localStorage.setItem('access_token_expires_at', expiresAt.toString());
        
        // 重新设置定时刷新Token
        dispatch('scheduleTokenRefresh', response.expires_in);
        
        return response;
      } catch (error) {
        // 刷新失败，执行登出操作
        dispatch('logout');
        throw error;
      }
    },
    
    // 设置定时刷新Token
    scheduleTokenRefresh({ commit, dispatch }, expiresIn) {
      // 清除之前的定时器
      dispatch('clearRefreshTimer');
      
      // 在过期前5分钟刷新Token
      const refreshTime = (expiresIn - 300) * 1000; // 提前5分钟刷新
      
      if (refreshTime > 0) {
        const timer = setTimeout(() => {
          dispatch('refreshToken');
        }, refreshTime);
        
        commit('SET_REFRESH_TIMER', timer); // 将定时器保存到timer的state中
      }
    },
    
    // 清除刷新定时器
    clearRefreshTimer({ commit, state }) {
      if (state.refreshTimer) {
        clearTimeout(state.refreshTimer);
        commit('SET_REFRESH_TIMER', null); // 移除定时器
      }
    },
    
    // 用户登出
    async logout({ commit, state, dispatch }) {
      try {
        // 清除定时器
        dispatch('clearRefreshTimer');
        
        // 如果有访问令牌，调用后端注销接口
        if (state.accessToken) {
          await userApi.logout({
            access_token: state.accessToken
          });
        }
      } catch (error) {
        console.error('注销接口调用失败:', error);
        // 不中断登出流程，继续清理本地状态
      } finally {
        // 清除本地状态
        commit('CLEAR_USER_INFO');
        
        // 清除localStorage
        localStorage.removeItem('user_info');
        localStorage.removeItem('access_token');
        localStorage.removeItem('refresh_token');
        localStorage.removeItem('isLogin');

        // 跳转到登录页面
        router.push('/login');
      }
    },
    
    // 初始化用户状态（页面刷新时调用）
    initUserState({ commit, dispatch }) {
      const userInfo = localStorage.getItem('user_info');
      const accessToken = localStorage.getItem('access_token');
      const refreshToken = localStorage.getItem('refresh_token');
      const isLogin = localStorage.getItem('isLogin');
      const accessTokenExpiresAt = localStorage.getItem('access_token_expires_at');
      
      // 检查token是否有效
      if (userInfo && accessToken && refreshToken && isLogin && accessTokenExpiresAt) {
        const now = Date.now();
        const expiresAt = parseInt(accessTokenExpiresAt);
        
        // 如果token已经过期，清除状态
        if (now >= expiresAt) {
          dispatch('logout');
          return;
        }
        
        // 如果token即将过期（剩余时间少于5分钟），立即刷新
        if (expiresAt - now < 300 * 1000) {
          dispatch('refreshToken');
        } else {
          // 恢复用户状态
          commit('SET_USER_INFO', JSON.parse(userInfo));
          commit('SET_ACCESS_TOKEN', accessToken);
          commit('SET_REFRESH_TOKEN', refreshToken);
          commit('SET_LOGIN_STATUS', true);
          
          // 重新设置定时刷新Token
          const expiresIn = Math.floor((expiresAt - now) / 1000);
          dispatch('scheduleTokenRefresh', expiresIn);
        }
      }
    }
  },
  
  getters: {
    // 获取用户信息
    userInfo: (state) => state.userInfo,
    
    // 获取访问令牌
    accessToken: (state) => state.accessToken,
    
    // 获取刷新令牌
    refreshToken: (state) => state.refreshToken,
    
    // 获取登录状态
    isLogin: (state) => state.isLogin,
    
    // 获取用户ID
    userId: (state) => state.userInfo?.id,
    
    // 获取用户名
    username: (state) => state.userInfo?.username
  }
});